package com.duke.javaagent.bytebuddy.pluggable;

import com.duke.javaagent.bytebuddy.pluggable.expansion.EnhanceContext;
import com.duke.javaagent.bytebuddy.pluggable.expansion.EnhancedInstance;
import com.duke.javaagent.bytebuddy.pluggable.interceptor.StringUtilInterceptor;
import net.bytebuddy.agent.builder.AgentBuilder;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.implementation.FieldAccessor;
import net.bytebuddy.implementation.MethodDelegation;
import net.bytebuddy.matcher.ElementMatchers;
import net.bytebuddy.utility.JavaModule;

import java.security.ProtectionDomain;

import static net.bytebuddy.jar.asm.Opcodes.ACC_PRIVATE;
import static net.bytebuddy.jar.asm.Opcodes.ACC_VOLATILE;

/**
 * @author gjy
 * @create 2024-12-10 12:44 PM
 */
public class ScriptTestObjTransformer implements AgentBuilder.Transformer {
    /**
     * New field name.
     */
    public static final String CONTEXT_ATTR_NAME = "_$EnhancedClassField_ws";
    @Override
    public DynamicType.Builder<?> transform(DynamicType.Builder<?> builder,
                                            TypeDescription typeDescription,
                                            ClassLoader classLoader,
                                            JavaModule javaModule,
                                            ProtectionDomain protectionDomain) {
        EnhanceContext context = new EnhanceContext();
        if (!typeDescription.isAssignableTo(EnhancedInstance.class)) {
            if (!context.isObjectExtended()) {
                builder = builder.defineField(
                                CONTEXT_ATTR_NAME, Object.class, ACC_PRIVATE | ACC_VOLATILE)
                        .implement(EnhancedInstance.class)
                        .intercept(FieldAccessor.ofField(CONTEXT_ATTR_NAME));
                context.extendObjectCompleted();
            }
        }

        System.out.println("ScriptTestObjTransformer 打印类的名字： "+ typeDescription.getActualName()+ "\n");
        return builder
                .method(ElementMatchers.named("run").or(ElementMatchers.named("scriptRun")))
                .intercept(MethodDelegation.to(new StringUtilInterceptor()));
    }
}
